package tr.richfacesext.components.imgviewer;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.media.jai.codec.ByteArraySeekableStream;

/**
 * 
 * @author mert
 *
 */
public class ImgViewerRenderer extends Renderer {
	
	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		ImgViewer imgViewer = (ImgViewer) component;
		if (imgViewer.getImage() != null) {
			BufferedImage bufferedImg = generateImg(imgViewer, imgViewer.getImage());
			
			putImgToSession(context, imgViewer, bufferedImg);
			
			writer.startElement("span", imgViewer);
			writer.startElement("img", imgViewer);
			writer.writeAttribute("id", "img_" + imgViewer.getId(), null);
			
			if (StringUtils.isNotEmpty(imgViewer.getStyle())) {
				writer.writeAttribute("style", imgViewer.getStyle(), null);
			}
				
			if (StringUtils.isNotEmpty(imgViewer.getOnclick())) 
				writer.writeAttribute("onclick", imgViewer.getOnclick(), null);
				
			if (imgViewer.getWidth() != null)
				writer.writeAttribute("width", String.valueOf(imgViewer.getWidth()), null);
			if (imgViewer.getHeight() != null)		
				writer.writeAttribute("height", String.valueOf(imgViewer.getHeight()), null);
			
//			important for portals, where relative urls are assigned to portal layout url, not the project context
			String contextPath = context.getExternalContext().getRequestContextPath();
			writer.writeAttribute("src", contextPath + "/" + ImgViewerConstants.IMAGEVIEWER_VIEW_ID + "?" + ImgViewerConstants.KEYVAL_IMAGEID + "=" + getImageSessionKey(imgViewer, bufferedImg), null);
			
			writer.endElement("img");
			writer.endElement("span");
		}
		else{
			logger.warn("Uh oh, image is null!");
		}
	}
	
	public BufferedImage scaleImg(ImgViewer ImgViewer, BufferedImage bi) {
		Image scaledImg = bi.getScaledInstance(ImgViewer.getThumbWidth().intValue(), ImgViewer.getThumbHeight().intValue(), Image.SCALE_SMOOTH);
		  
		BufferedImage thumbBi = new BufferedImage(ImgViewer.getThumbWidth().intValue(), ImgViewer.getThumbHeight().intValue(), BufferedImage.TYPE_INT_BGR);
		Graphics g = thumbBi.createGraphics();
		g.drawImage(scaledImg, 0, 0, null);
		
		return thumbBi;
	}
	
	private BufferedImage generateImg(ImgViewer imgViewer, byte[] img) throws ImageFormatException, IOException {
		BufferedImage bufferedImg = null;
		
		try {
			RenderedOp renderedOp = JAI.create("stream", new ByteArraySeekableStream(img));
			bufferedImg = renderedOp.getAsBufferedImage();
		}
		catch (ImageFormatException e) {
			//log.error("Couldn't generate Image", e);
		}
		
		if (imgViewer.getThumbnail())
			bufferedImg = scaleImg(imgViewer, bufferedImg);
		
		return bufferedImg;
	}

	@SuppressWarnings("unchecked")
	private void putImgToSession(FacesContext context, ImgViewer ImgViewer, BufferedImage bufferedImage) {
		Object session = context.getExternalContext().getSession(true); 
		if (session instanceof HttpSession){ 
			Map sessionMap = context.getExternalContext().getSessionMap();
			String sessionKey=getImageSessionKey(ImgViewer, bufferedImage);
			sessionMap.put(sessionKey, bufferedImage);
		}
	}

	private String getImageSessionKey(ImgViewer ImgViewer, BufferedImage bufferedImage) {
		return bufferedImage.hashCode() + "_" + ImgViewer.getId();
	}	
}
